/* this header defines the type message. It separates it from the functions that access a message. It also contains the functions used to access a message, even in a UP. We use such functions because it makes maintainance easier as the internal structure of a message can change without affecting anything else. Those functions are NOT accessed through a syscall by the UPs because they act on a piece of memory owned by the process (the message). Just like the functions in string.h, they form an abstraction layer to make life easier for the programmer (and the system designer who can change the type message without worrying about breaking old programs as long as he keeps those functions up to date). */

#ifndef MESSAGE_DEFINITION_H
#define MESSAGE_DEFINITION_H

#include "null.h"
#include "error_codes.h"
#include "types.h"

/* flags definition */
#define INT_DATA 1
#define STR_DATA 2
#define PINFO_DATA 3

//the priority field is also the message's tag. The following tag is only used for supervision messages
#define SUPERVISION_MESSAGE 0

/* datastructures */

/* Useful information about a process that a message can carry */
typedef struct{
  uint32_t priority;
  int32_t program_id;
  int32_t parent;
  int32_t status; //is only relevant in a supervision message
}process_information;

typedef struct{
  int32_t from;
  int32_t to;
  int32_t priority;
  union{
    char* str_data;
    int int_data;
    process_information pinfo_data;
  }data;
  int8_t data_flag; // 0 if the message carries a string, 1 for an integer and 2 for a process_information structure
}message;

/* define a proper type for the functions */
typedef message* message_t;

/*getters, almost all those functions returns INCORRECT_REQUEST if called with a NULL pointer or if the data flag does not correspond */

int32_t message_get_from(message_t target);

int32_t message_get_to(message_t target);

int8_t message_get_data_flag(message_t target);

int32_t message_get_priority(message_t target);

/* Returns a pointer to the string stored in target if the data flag is set to string. Returns NULL otherwise. */
char* message_get_str_value(message_t target);

/* Returns the integer stored in target if the data flag is set to int. Returns 0 otherwise. */
int32_t message_get_int_value(message_t target);

int32_t message_get_pinfo_priority_value(message_t target);

int32_t message_get_pinfo_program_id_value(message_t target);

int32_t message_get_pinfo_parent_value(message_t target);

int32_t message_get_pinfo_status_value(message_t target);
#endif
